package main

import (
	"env_serial_water/config"
	"fmt"
	"github.com/tarm/serial"
	"log"
	"math/rand"
	"strings"
	"sync"
	"time"
)

var gw sync.WaitGroup

func hexCheckSum(data []byte) string {
	var sum byte
	for _, b := range data {
		sum ^= b
	}
	return fmt.Sprintf("%02x", sum)
}

func appendHexCheck(data string) string {
	return data + strings.ToUpper(hexCheckSum([]byte(data[1:len(data)-1]))) + "\r\n"
}

func latLon(min float32, max float32) string {
	randomFloat := min + rand.Float32()*(max-min)
	degrees := int(randomFloat)
	minutes := (randomFloat - float32(degrees)) * 60.0
	ddmmmmmm := float32(degrees)*100.0 + minutes
	return fmt.Sprintf("%.5f", ddmmmmmm)
}

func mockWater(ch chan<- string) {
	for {
		// $GNRMC,083520.000,A,3158.06309,N,12055.50771,E,0.001,287.40,200924,,,A*4D
		dateTime := time.Now().Add(-8 * time.Hour)
		gnrmc := fmt.Sprintf("$GNRMC,%s.000,A,%s,N,%s,E,2.106,41.28,%s,,,A*",
			dateTime.Format("150405"),
			latLon(23.660, 23.661),
			latLon(117.509, 117.510),
			dateTime.Format("020106"),
		)
		ch <- appendHexCheck(gnrmc)
		time.Sleep(time.Second)
	}
}

func consoleWater(ch <-chan string) {
	for {
		data := <-ch
		fmt.Printf("%s\n", data)
	}
}

func writeWater(ch <-chan string) {
	serialConfig := &serial.Config{
		Name: config.Conf.SerialName,
		Baud: config.Conf.SerialBaud,
	}
	port, err := serial.OpenPort(serialConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer func(port *serial.Port) {
		err := port.Close()
		if err != nil {
			fmt.Println(err)
		}
	}(port)

	for {
		data := <-ch
		currentTime := time.Now()
		fmt.Printf("%s:%s=>%s", currentTime.Format("2006-01-02 15:04:05"), config.Conf.SerialName, data)
		_, err := port.Write([]byte(data))
		if err != nil {
			log.Fatal(err)
		}
	}
}

func main() {
	gw.Add(1)
	var waterCh = make(chan string, 8)
	go mockWater(waterCh)
	go writeWater(waterCh)
	gw.Wait()
}
